﻿namespace pdfer
{
    public class PdfDocument : IDisposable
    {
        // 打开pdf文件
        private readonly Stream _stream;
        private readonly String? _pwd;
        private Boolean _disposed = false;
        internal readonly PdfParser pdfParser;
        private Dictionary<Int32, PdfPage> pdfPages = [];

        public PdfDocument(String filePath, String? pwd = null)
        {
            var fi = new FileInfo(filePath);
            if (!fi.Exists) 
            {
                throw new FileNotFoundException(filePath);
            }
            _pwd = pwd;
            _stream = fi.OpenRead();
            pdfParser = new PdfParser(_stream, pwd);
        }

        public PdfDocument(Stream stream, String? pwd = null) 
        {
            _pwd = pwd;
            _stream = stream;
            pdfParser = new PdfParser(_stream, pwd);
        }

        private PdfMetaData? _metadata;
        /// <summary>
        /// 读取基本信息
        /// </summary>
        public PdfMetaData Metadata 
        { 
            get 
            {
                ThrowIfDisposed();
                if (_metadata == null)
                {
                    InnerReadMetadate();
                }
                return _metadata;
            } 
        }

        private void InnerReadMetadate()
        {
            // 读取尾部节点中的Info指向的对象
            var docInfo = pdfParser.GetDocumentInfo();

            if(docInfo == null)
            {
                _metadata = new();
            }
            else
            {
                var pdfMetadata = new PdfMetaData
                {
                    Author = docInfo.Author,
                    CreationDate = docInfo.CreationDate,
                    Creator = docInfo.Creator,
                    Keywords = docInfo.Keywords,
                    ModDate = docInfo.ModDate,
                    Producer = docInfo.Producer,
                    Subject = docInfo.Subject,
                    Title = docInfo.Title,
                    Version = pdfParser.Version
                };
                _metadata = pdfMetadata;
            }
        }

        private Int32? _page;
        /// <summary>
        /// 读取页码信息
        /// </summary>
        public Int32 Page
        {
            get 
            {
                ThrowIfDisposed();
                if (!_page.HasValue)
                {
                    //InnerReadPageInfo();
                    _page = pdfParser.DocumentTree?.Count;
                }
                return _page.Value;
            }
        }

        private PdfBookmarkCollection? _pdfBookmarks;
        /// <summary>
        /// 获取书签
        /// </summary>
        public PdfBookmarkCollection PdfBookmarks 
        { 
            get 
            {
                ThrowIfDisposed();
                if (_pdfBookmarks == null)
                {
                    _pdfBookmarks = pdfParser.GetBookmarkInfo();
                }
                return _pdfBookmarks;
            }
        }

        /// <summary>
        /// TODO: 获取指定页的图片
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public Byte[][] GetImages(Int32 page)
        {
            ThrowIfDisposed();
            if(page < 0 || page >= Page)
            {
                return [];
            }
            // 获取指定页的指定类型的对象
            // 暂时的问题 内联图片没有处理（一般内联图片比较少）
            var result = pdfParser.GetImages(page);
            return result;
        }
        // TODO: 获取指定页的文本
        // TODO: 获取带位置信息的文本
        // TODO: 渲染指定页为图片

        /// <summary>
        /// TODO 尺寸指定
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public Byte[] Render(Int32 page)
        {
            ThrowIfDisposed();

            var pdfPage = GetPage(page);

            Byte[] data = pdfPage.Render();
            return data;
        }

        public List<String> GetText(Int32 page)
        {
            ThrowIfDisposed();
            var pdfPage = GetPage(page);
            return pdfPage.GetText();
        }

        /// <summary>
        /// 获取指定页对象
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public PdfPage GetPage(Int32 page)
        {
            ThrowIfDisposed();

            if (pdfPages.TryGetValue(page, out var pdfPage))
            {
                return pdfPage;
            }
            else 
            {
                var _ = new PdfPage(this, page);
                pdfPages.Add(page, _);
                return _;
            }
        }


        public void Dispose()
        {
            _disposed = true;
            if (_stream != null) 
            {
                _stream.Dispose();
            }
        }

        private void ThrowIfDisposed() 
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }


    }
}
